/*
 * Created on 2004.8.12
 *
 */
package lv.solcraft.replication.common;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Data transfer object for operation.
 * 
 * @author Ilgvars
 */
public class OperDTO implements Serializable {

    private List<Field> fields;

    private List<Field> descrFields;

    private Map<String, byte[]> blobFields = new HashMap<String, byte[]>();

    private String table;

    private int recordSiteId;

    private int recordId;

    private int operId;

    private long sysOperId;

    private String type;

    private Date dateTime;

    private int operOwnerSiteId;

    private String operOrder;

    private List<OperState> operStates;

    public transient int marker = 0;

    public OperDTO() {
        this.fields = new ArrayList<Field>(1);
        this.descrFields = new ArrayList<Field>(1);
        this.operStates = new ArrayList<OperState>(1);
    }

    public Date getDateTime() {
        return dateTime;
    }

    public void setDateTime(Date dateTime) {
        this.dateTime = dateTime;
    }

    public int getOperId() {
        return operId;
    }

    public void setOperId(int operId) {
        this.operId = operId;
    }

    public int getOperOwnerSiteId() {
        return operOwnerSiteId;
    }

    public void setOperOwnerSiteId(int operOwnerSiteId) {
        this.operOwnerSiteId = operOwnerSiteId;
    }

    public int getRecordId() {
        return recordId;
    }

    public void setRecordId(int recordId) {
        this.recordId = recordId;
    }

    public int getRecordSiteId() {
        return recordSiteId;
    }

    public void setRecordSiteId(int recordSiteId) {
        this.recordSiteId = recordSiteId;
    }

    public long getSysOperId() {
        return sysOperId;
    }

    public void setSysOperId(long sysOperId) {
        this.sysOperId = sysOperId;
    }

    public String getTable() {
        return table.trim();
    }

    public void setTable(String table) {
        this.table = table.trim();
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public List<Field> getFields() {
        return fields;
    }

    public void addField(String name, String value) {
        Field fld = new Field(name, value);

        if (fields.contains(fld)) {
            throw new IllegalArgumentException("Field " + name + " already exists in oper.");
        }

        fields.add(fld);
    }

    public class Field implements Serializable {
        private String name;

        private String value;

        public Field(String name, String value) {
            if (name == null) {
                throw new NullPointerException("Field name is null.");
            }
            this.name = name.trim();
            this.value = value;
        }

        public String getName() {
            return name;
        }

        public String getValue() {
            return value;
        }

        public void setName(String name) {
            this.name = name;
        }

        public void setValue(String value) {
            this.value = value;
        }

        public boolean equals(Object obj) {
            if (obj == null) {
                return false;
            }
            if (!(obj instanceof Field)) {
                return false;
            }

            Field fld = (Field) obj;

            return this.name.equals(fld.name);
        }

        public String toString() {
            return "name [" + name + "], value [" + value + "]";
        }

        public int hashCode() {
            return name.hashCode();
        }
    }

    public class OperState implements Serializable {
        private int siteId;

        private String state;

        private String message;

        public OperState(int id, String state, String message) {
            siteId = id;
            this.state = state;
            this.message = message;
        }

        public String getMessage() {
            return message;
        }

        public int getSiteId() {
            return siteId;
        }

        public String getState() {
            return state;
        }

        @Override
        public boolean equals(Object obj) {
            if (!(obj instanceof OperState)) {
                return false;
            }

            OperState other = (OperState) obj;
            return other.siteId == this.siteId;
        }

        @Override
        public int hashCode() {
            return new Integer(siteId).hashCode();
        }

        @Override
        public String toString() {
            return "[" + siteId + ", " + state + ", " + message + "]";
        }

    }

    public boolean isTypeDelete() {
        return ReplicationConst.TYPE_DELETE.equals(type);
    }

    public boolean isTypeInsert() {
        return ReplicationConst.TYPE_INSERT.equals(type);
    }

    public boolean isTypeUpdate() {
        return ReplicationConst.TYPE_UPDATE.equals(type);
    }

    public List<Field> getDescrFields() {
        return descrFields;
    }

    public void addDescrField(String name, String value) {
        Field fld = new Field(name, value);

        if (descrFields.contains(fld)) {
            throw new IllegalArgumentException("Descr field " + name + " already exists in oper.");
        }

        descrFields.add(fld);
    }

    public String toString() {
        StringBuffer b = new StringBuffer();
        b.append("OPERATION: \n");
        b.append("\t sysOperId: ").append(sysOperId).append("\n");
        b.append("\t operOwnerSiteId: ").append(operOwnerSiteId).append("\n");
        b.append("\t operId: ").append(operId).append("\n");
        b.append("\t type: ").append(type).append("\n");
        b.append("\t table: ").append(table).append("\n");
        b.append("\t recordSiteId: ").append(recordSiteId).append("\n");
        b.append("\t recordId: ").append(recordId).append("\n");
        b.append("\t datetime: ").append(dateTime).append("\n");
        b.append("\t fields: ").append("\n");
        for (Field fld : fields) {
            b.append("\t\t ").append(fld).append("\n");
        }
        b.append("\t descrFields: ").append("\n");
        for (Field fld : descrFields) {
            b.append("\t\t ").append(fld).append("\n");
        }
        return b.toString();
    }

    public String getOperOrder() {
        return operOrder;
    }

    public void setOperOrder(String operOrder) {
        this.operOrder = operOrder;
    }

    public List<OperState> getOperStates() {
        return operStates;
    }

    public void setState(int siteId, String state, String message) {
        OperState oState = new OperState(siteId, state, message);
        operStates.remove(oState);
        operStates.add(oState);
    }

    public Map<String, byte[]> getBlobFields() {
        return blobFields;
    }

}
